package com.badboy.mycarbon.login.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.badboy.mycarbon.login.entity.SysAccount;
import com.badboy.mycarbon.login.mapper.LoginMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class LoginService {

    @Autowired
    private LoginMapper loginMapper;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    // Redis Key前缀
    private static final String LOGIN_KEY_PREFIX = "login:";       // 登录状态前缀
    private static final String PHONE_CODE_REGISTER_PREFIX = "phone_code_register:"; // 注册手机号验证码前缀
    private static final String PHONE_CODE_FORGOT_PASSWORD_PREFIX = "phone_code_forgot_password:"; // 忘记密码手机号验证码前缀

    // 登录 Token 过期时间（1 小时）
    private static final long LOGIN_EXPIRE_TIME = 1;
    private static final TimeUnit LOGIN_EXPIRE_TIME_UNIT = TimeUnit.HOURS;

    // 常量定义（对应数据库字典值）
    public static final String STATUS_NORMAL = "01";    // 正常状态

    // 验证码有效期（5分钟）
    private static final long PHONE_CODE_EXPIRE_TIME = 5;

    /**
     * 用户登录
     */
    public Map<String, Object> login(String accountName, String password) {
        // 查询账户
        SysAccount account = loginMapper.selectOne(
                new LambdaQueryWrapper<SysAccount>()
                        .eq(SysAccount::getAccountName, accountName)
        );

        // 校验账户和密码
        if (account == null) {
            throw new RuntimeException("账户不存在");
        }

        String encryptedPassword = DigestUtils.md5DigestAsHex(password.getBytes());
        if (!encryptedPassword.equals(account.getPassword())) {
            throw new RuntimeException("密码错误");
        }

        // 生成 Token
        String token = generateToken();
        String redisKey = LOGIN_KEY_PREFIX + account.getId();
        // 设置 Token 过期时间为 1 小时
        redisTemplate.opsForValue().set(redisKey, token, LOGIN_EXPIRE_TIME, LOGIN_EXPIRE_TIME_UNIT);

        // 更新数据库中的 Token
        loginMapper.update(
                null,
                new LambdaUpdateWrapper<SysAccount>()
                        .eq(SysAccount::getId, account.getId())
                        .set(SysAccount::getToken, token)
        );

        Map<String, Object> result = new HashMap<>();
        result.put("code", 200);
        result.put("message", "登录成功");
        result.put("token", token);
        return result;
    }

    /**
     * 用户退出登录
     */
    public void logout(Long accountId) {
        // 从Redis中删除登录状态
        String redisKey = LOGIN_KEY_PREFIX + accountId;
        redisTemplate.delete(redisKey);

        // 清空数据库中的Token
        loginMapper.update(
                null,
                new LambdaUpdateWrapper<SysAccount>()
                        .eq(SysAccount::getId, accountId)
                        .set(SysAccount::getToken, "")
        );
    }

    /**
     * 用户注册
     */
    public void register(String accountName, String username, String password,
                         String confirmPassword, String phone, String verifyCode) {
        // 校验验证码
        String redisKey = PHONE_CODE_REGISTER_PREFIX + phone;
        String storedCode = (String) redisTemplate.opsForValue().get(redisKey);

        if (storedCode == null || !storedCode.equals(verifyCode)) {
            throw new RuntimeException("验证码无效或已过期");
        }

        // 校验两次密码
        if (!password.equals(confirmPassword)) {
            throw new RuntimeException("两次输入的密码不一致");
        }

        // 检查账户名是否已存在
        SysAccount existingAccount = loginMapper.selectOne(
                new LambdaQueryWrapper<SysAccount>()
                        .eq(SysAccount::getAccountName, accountName)
        );

        if (existingAccount != null) {
            throw new RuntimeException("账户名已被注册");
        }

        // 创建新账户
        SysAccount newAccount = new SysAccount();
        newAccount.setAccountName(accountName);
        newAccount.setUsername(username);
        newAccount.setPassword(DigestUtils.md5DigestAsHex(password.getBytes()));
        newAccount.setPhone(phone);
        // 将账户状态设置为正常
        newAccount.setAccountStatus(STATUS_NORMAL);
        newAccount.setCreatedTime(new Date());
        newAccount.setUpdatedTime(new Date());

        // 插入数据库
        loginMapper.insert(newAccount);

        // 删除验证码
        // 修改为使用 PHONE_CODE_REGISTER_PREFIX
        redisKey = PHONE_CODE_REGISTER_PREFIX + phone;
        redisTemplate.delete(redisKey);
    }

    /**
     * 发送手机号验证码
     * @param phone 手机号
     * @param scene 场景，register 表示注册，forgot_password 表示忘记密码
     * @return 根据场景生成的提示消息
     */
    public String sendPhoneCode(String phone, String scene) {
        // 生成6位随机验证码
        String verifyCode = String.format("%06d", (int) (Math.random() * 1000000));

        String redisKey;
        String message;
        if ("register".equals(scene)) {
            redisKey = PHONE_CODE_REGISTER_PREFIX + phone;
            message = String.format("【注册专用】验证码已发送到手机号：%s，验证码：%s，5分钟内有效，请妥善保管用于完成注册操作。", phone, verifyCode);
        } else if ("forgot_password".equals(scene)) {
            redisKey = PHONE_CODE_FORGOT_PASSWORD_PREFIX + phone;
            message = String.format("【忘记密码专用】验证码已发送到手机号：%s，验证码：%s，5分钟内有效，请妥善保管用于重置密码操作。", phone, verifyCode);
        } else {
            throw new RuntimeException("不支持的验证码发送场景");
        }

        // 存入Redis
        redisTemplate.opsForValue().set(redisKey, verifyCode, PHONE_CODE_EXPIRE_TIME, TimeUnit.MINUTES);

        // 实际项目中需要集成短信服务
        System.out.println(message);
        return message;
    }

    /**
     * 验证Token有效性
     */
    public boolean validateToken(Long accountId, String token) {
        // 从Redis获取缓存的Token
        String redisKey = LOGIN_KEY_PREFIX + accountId;
        String cachedToken = (String) redisTemplate.opsForValue().get(redisKey);

        // 校验Token
        return token != null && token.equals(cachedToken);
    }

    /**
     * 忘记密码
     */
    public boolean forgotPassword(String phone, String verifyCode, String newPassword) {
        // 校验手机号验证码
        String redisKey = PHONE_CODE_FORGOT_PASSWORD_PREFIX + phone;
        String storedCode = (String) redisTemplate.opsForValue().get(redisKey);

        if (storedCode == null || !storedCode.equals(verifyCode)) {
            throw new RuntimeException("验证码不正确");
        }

        // 查询用户是否存在
        SysAccount account = loginMapper.selectOne(
                new LambdaQueryWrapper<SysAccount>()
                        .eq(SysAccount::getPhone, phone)
        );

        if (account == null) {
            throw new RuntimeException("用户不存在");
        }

        // 更新密码（使用 LambdaUpdateWrapper）
        int result = loginMapper.update(
                null,
                new LambdaUpdateWrapper<SysAccount>()
                        .eq(SysAccount::getId, account.getId())
                        .set(SysAccount::getPassword, DigestUtils.md5DigestAsHex(newPassword.getBytes()))
                        .set(SysAccount::getUpdatedTime, new Date())
        );

        // 删除验证码
        redisTemplate.delete(redisKey);

        return result > 0;
    }

    /**
     * 生成Token
     */
    private String generateToken() {
        return UUID.randomUUID().toString().replace("-", "");
    }
}